/*
 *    Copyright 2009-2012 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.reflection.property;

import org.apache.ibatis.annotations.NeedReadAgain;

import java.util.Iterator;

/**
 * @author Clinton Begin
 */

/**
 * 属性分解为标记，迭代子模式
 * 如person[0].birthdate.year，将依次取得person[0], birthdate, year
 * <p>
 * 这个类是property包中的重量级类，该类会被reflection包中其他的类频繁的引用到。
 * 这个类实现了Iterable和Iterator这两个接口，
 * 但在使用时经常被用到的是Iterator接口中的hasNext这个函数。
 * 我们着重了解这个类的属性和构造函数：
 */
@NeedReadAgain(designPattern = "迭代器设计模式 https://www.jianshu.com/p/3dd7b4e73561")
public class PropertyTokenizer implements Iterable<PropertyTokenizer>, Iterator<PropertyTokenizer> {
    //例子： person[0].birthdate.year
    private String name; //person
    private String indexedName; //person[0]
    private String index; //0
    private String children; //birthdate.year

    public PropertyTokenizer(String fullname) {
        //person[0].birthdate.year
        //找.

        // 对参数进行第一次处理，通过“.”分隔符将propertyName分作两部分
        int delim = fullname.indexOf('.');
        if (delim > -1) {
            name = fullname.substring(0, delim);
            children = fullname.substring(delim + 1);
        } else {
            //找不到.的话，取全部部分
            name = fullname;
            children = null;
        }
        indexedName = name;
        //把中括号里的数字给解析出来

        // 对name进行二次处理,去除“[...]”，并将方括号内的内容赋给index属性，
        // 如果name属性中包含“[]”的话
        delim = name.indexOf('[');
        if (delim > -1) {
            // 先取index内容再截取name更为方便些，要不然还需要一个临时变量，需要三步才能实现
            // 这里包含了一个前提：传入的参数如果有有[,则必然存在],并且是属性的最后一个字符
            index = name.substring(delim + 1, name.length() - 1);
            name = name.substring(0, delim);
        }
    }

    public String getName() {
        return name;
    }

    public String getIndex() {
        return index;
    }

    public String getIndexedName() {
        return indexedName;
    }

    public String getChildren() {
        return children;
    }

    @Override
    public boolean hasNext() {
        return children != null;
    }

    //取得下一个,非常简单，直接再通过儿子来new另外一个实例
    @Override
    public PropertyTokenizer next() {
        return new PropertyTokenizer(children);
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException("Remove is not supported, as it has no meaning in the context of properties.");
    }

    @Override
    public Iterator<PropertyTokenizer> iterator() {
        return this;
    }

    public static void main(String[] args) {
        String s = new String("person[0].birthdate.year");
        PropertyTokenizer tokenizer = new PropertyTokenizer(s);
//        person
//        person[0]
//        0
//        birthdate.year
        System.out.println(tokenizer.name);
        System.out.println(tokenizer.indexedName);
        System.out.println(tokenizer.index);
        System.out.println(tokenizer.children);
        System.out.println("=================");
        tokenizer = tokenizer.iterator().next();
//        birthdate
//        birthdate
//        null
//        year
        System.out.println(tokenizer.name);
        System.out.println(tokenizer.indexedName);
        System.out.println(tokenizer.index);
        System.out.println(tokenizer.children);
    }
}
